import { dialog, ipcMain } from "electron";
import puppeteer, { Page, Browser as PuppeteerBrowser } from "puppeteer";
import { install, Browser } from "@puppeteer/browsers";
import * as path from "path";
import fs from "fs";
import { cacheDir } from "./rootdir";
import { getMainWindow } from "./mainwindow";
import { T_ChromeListItem } from "@shared/types/chromeList";
type ChromeItem = {
  page: Page;
  id: T_ChromeListItem["id"];
};
class BrowserBridge {
  private chromeList: ChromeItem[] = [];
  browser: PuppeteerBrowser | null = null;
  async init() {
    // 打开浏览器
    ipcMain.handle("puppeteerBrowser", async (_, urlItem: T_ChromeListItem) => {
      try {
        if (!this.browser) {
          await this.launchBrowser();
        }
        await this.openBrowser(urlItem);
        return Promise.resolve("success");
      } catch (err) {
        console.log(err, "err");
        return null;
      }
    });
  }
  async launchBrowser() {
    const chromePath = this.getChromeExePath(path.join(cacheDir(), "chrome_browser", "chrome"));
    if (!chromePath) {
      this.downloadBrowser();
      return Promise.reject("fail");
    }
    try {
      const args = await this.getBrowserArgs();
      const browserOpts: any = {
        args,
        headless: false,
        defaultViewport: null, //
        ignoreDefaultArgs: ["--enable-automation"],
        devtools: false,
        dumpio: true,
        executablePath: chromePath
      };
      // 设置用户数据目录
      browserOpts.userDataDir = "./userdata";
      const browserLaunch = await puppeteer.launch(browserOpts).catch(() => {
        return Promise.reject("fail");
      });
      if (browserLaunch) {
        this.browser = browserLaunch;
        // 监听浏览器如果关闭，则重置下次launch
        browserLaunch.on("disconnected", () => {
          this.browser = null;
        });
      } else {
        return Promise.reject("fail");
      }
    } catch (err) {
      console.log(err);
      return Promise.reject("fail");
    }
  }
  async getBrowserArgs(): Promise<string[]> {
    const args = [
      "--force-color-profile=srgb",
      "--no-first-run",
      "--no-default-browser-check",
      "--metrics-recording-only",
      "--disable-background-mode",
      // 移除 "Chrome 正在受自动化软件控制" 的提示
      "--disable-infobars",
      "--unhandled-rejections=strict",
      "--no-sandbox",
      "--disable-setuid-sandbox"
    ];
    return args;
  }

  // 打开浏览器
  async openBrowser(browserConfig: T_ChromeListItem) {
    if (this.browser) {
      const url = browserConfig.domain + browserConfig.url;
      const context = await this.browser.createBrowserContext();
      const newPage = await context.newPage();
      if (this.chromeList.length === 0) {
        const pages = await this.browser?.pages();
        pages[0].close();
      }
      this.chromeList.push({
        id: browserConfig.id,
        page: newPage
      });
      // 关闭页面时，从列表中移除
      newPage.on("close", () => {
        const id = this.chromeList.find((item) => item.page == newPage)?.id;
        this.chromeList = this.chromeList.filter((item) => item.page !== newPage);
        const mainWindow = getMainWindow();
        mainWindow?.webContents.send("closeBrowserPage", id);
        // mac特殊处理
        if (process.platform === "darwin" && this.chromeList.length === 0) {
          this.browser?.close();
        }
      });
      /**
       * @params {waitUntil}: 等待页面加载完成
       * waitUntil: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
       * load: 等待页面的 load 事件触发，意味着所有资源都已加载完成。
       * domcontentloaded: 等待页面的 DOMContentLoaded 事件触发，意味着 HTML 被完全加载和解析，但不等待样式表、图像和子框架的加载
       * networkidle0：等待网络连接空闲 500 毫秒。适用于在没有进一步网络请求时认为页面已加载完成。
       * networkidle2：等待网络连接空闲 500 毫秒，并且有两个或更少的网络连接
       */
      await newPage.goto(url, { waitUntil: "domcontentloaded" });
      if (browserConfig.account && browserConfig.password) {
        const frame = await newPage.waitForFrame(async (_frame) => {
          return _frame.url().includes("pages/login/cellphone");
        });
        const loginPage = frame.page();
        if (loginPage) {
          await loginPage
            .locator(".login-layout__extra > div > a")
            .filter((a) => a.innerText === "账号登录")
            .click();
          await loginPage.locator("#basic_account").fill(browserConfig.account);
          await loginPage.locator("#basic_pswAccount").fill(browserConfig.password);
          await loginPage.locator(".psw-login__submit").click();
        }
      }
    }
  }

  // 下载浏览器
  async downloadBrowser() {
    const chromePath = path.join(cacheDir(), "chrome_browser");
    return new Promise((resolve, reject) => {
      install({
        browser: Browser.CHROME,
        cacheDir: chromePath,
        buildId: "131.0.6778.204",
        downloadProgressCallback: (downloadedBytes, totalBytes) => {
          // console.log((downloadedBytes / totalBytes) * 100)
          // setInterval(() => {
          getMainWindow()!.webContents.send(
            "downloadChromeProgress",
            (downloadedBytes / totalBytes) * 100
          );
          // }, 1000)
          return resolve("success");
        }
      }).catch((e) => {
        reject(e);
      });
    });
  }
  getChromeExePath(basePath: string): string {
    if (!fs.existsSync(basePath)) {
      return "";
    }
    const dirs = fs.readdirSync(basePath);
    if (dirs.length === 0) {
      return "";
    }
    for (const subDir of dirs) {
      const filePath = path.join(basePath, subDir);
      const stats = fs.statSync(filePath);
      if (!stats.isDirectory()) continue;
      if (process.platform === "win32") {
        if (subDir.startsWith("chrome-win")) {
          return path.join(filePath, "chrome.exe");
        }
      } else if (process.platform === "darwin") {
        if (subDir.startsWith("Google Chrome for")) {
          return path.join(filePath, "Contents", "MacOS", "Google Chrome for Testing");
        }
      } else {
        throw new Error("Unsupported platform");
      }
      return this.getChromeExePath(filePath);
    }
    return "";
  }
  getCurChromeLocalPath() {
    console.log("puppeteer使用浏览器的路径:", puppeteer.executablePath());
  }
  // 获取浏览器安装路径
  async getChromeInstalledPath() {
    try {
      const ChromeLauncher = await import("chrome-launcher");
      const chromePaths = ChromeLauncher.Launcher.getInstallations();
      if (chromePaths.length > 0) {
        const defaultChromePath = chromePaths[0].toString();
        return defaultChromePath;
      } else {
        dialog.showErrorBox("检查谷歌浏览器信息错误", "请安装谷歌浏览器");
        throw new Error("请安装谷歌浏览器");
      }
    } catch (error) {
      dialog.showErrorBox("检查谷歌浏览器信息错误", `获取谷歌浏览器安装目录错误: ${error}`);
      throw new Error(`获取谷歌浏览器安装目录错误: ${error}`);
    }
  }
}
export default new BrowserBridge();
